﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using LimaLims.Application.Service.Sys.Dto;
using LimaLims.Core;
using LimaLims.Core.Entity.System;
using log4net.Core;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LimaLims.Application.Service.Sys
{
    /// <summary>
    /// 字典类型服务
    /// </summary>
    [Route("api")]
    public class SysDictTypeService : ISysDictTypeService, IDynamicApiController, ITransient
    {
        private readonly IRepository<SysDictType> _sysDictTypeRep;  // 字典类型表仓储
        private readonly ISysDictDataService _sysDictDataService;

        public SysDictTypeService(ISysDictDataService sysDictDataService,
                                  IRepository<SysDictType> sysDictTypeRep)
        {
            _sysDictDataService = sysDictDataService;
            _sysDictTypeRep = sysDictTypeRep;
        }

        /// <summary>
        /// 添加字典类型
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("sysDictType/add")]
        public async Task AddDictType(AddDictTypeInput input)
        {
            var isExist = await _sysDictTypeRep.AnyAsync(u => u.Name == input.Name || u.Code == input.Code, false);
            if (isExist) throw Oops.Oh("字典类型已存在,名称或编码重复");

            var dictType = input.Adapt<SysDictType>();
            await _sysDictTypeRep.InsertAsync(dictType);
        }
        /// <summary>
        /// 删除字典类型
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("sysDictType/delete")]
        [UnitOfWork]
        public async Task DeleteDictType(long id)
        {
            var dictType = await _sysDictTypeRep.FirstOrDefaultAsync(u => u.Id == id);
            if (dictType == null) throw Oops.Oh("字典类型不存在");
            await dictType.DeleteAsync();
            await _sysDictDataService.DeleteByTypeId(dictType.Id);
        }

        /// <summary>
        /// 字典类型详情
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("sysDictType/detail")]
        public async Task<SysDictType> GetDictType(long id)
        {
            return await _sysDictTypeRep.FirstOrDefaultAsync(u => u.Id == id, false);
        }

        /// <summary>
        /// 获取字典类型列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("sysDictType/list")]
        public async Task<List<SysDictType>> GetDictTypeList()
        {
            return await _sysDictTypeRep.DetachedEntities.Where(u => u.ValidStatus).ToListAsync();
        }

        [HttpGet("sysDictType/dictDatalist")]
        public async Task<List<SysDictData>> GetDictTypeByTypeId(string code)
        {
            var dictType = await _sysDictTypeRep.FirstOrDefaultAsync(u => u.Code == code, false);
            if (dictType == null) throw Oops.Oh("字典类型不存在");
            return await _sysDictDataService.GetDictDataListByDictTypeId(dictType.Id);
        }

        /// <summary>
        /// 分页查询字典类型
        /// </summary>
        /// <returns></returns>
        [HttpGet("sysDictType/page")]
        public async Task<PageResult<SysDictType>> QueryDictTypePageList([FromQuery] DictTypePageInput input)
        {
            var code = !string.IsNullOrEmpty(input.Code?.Trim());
            var name = !string.IsNullOrEmpty(input.Name?.Trim());
            var dictTypes = await _sysDictTypeRep.DetachedEntities
                                  .Where((code, u => EF.Functions.Like(u.Code, $"%{input.Code.Trim()}%")),
                                         (name, u => EF.Functions.Like(u.Name, $"%{input.Name.Trim()}%")))
                                  .OrderBy(u => u.Sort)
                                  .ToADPagedListAsync(input.PageNo, input.PageSize);
            return dictTypes;
        }


        /// <summary>
        /// 更新字典类型
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("sysDictType/edit"),]
        public async Task UpdateDictType(UpdateDictTypeInput input)
        {
            var isExist = await _sysDictTypeRep.AnyAsync(u => u.Id == input.Id, false);
            if (!isExist) throw Oops.Oh("字典类型不存在");

            // 排除自己并且判断与其他是否相同
            isExist = await _sysDictTypeRep.AnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id, false);
            if (isExist) throw Oops.Oh("字典类型已存在,名称或编码重复");

            var dictType = input.Adapt<SysDictType>();
            await _sysDictTypeRep.UpdateAsync(dictType, ignoreNullValues: true);
        }

        #region 前台
        /// <summary>
        /// 字典类型与字典值构造的字典树
        /// </summary>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("sysDictType/tree")]
        public async Task<List<DictTreeOutput>> GetDictTree()
        {
            return await _sysDictTypeRep.DetachedEntities.Select(u => new DictTreeOutput
            {
                Id = u.Id,
                Code = u.Code,
                Name = u.Name,
                Children = u.SysDictDatas.Select(c => new DictTreeOutput
                {
                    Id = c.Id,
                    Pid = c.DictTypeId,
                    Code = c.Code,
                    Name = c.Value
                }).ToList()
            }).ToListAsync();
        }

        /// <summary>
        /// 获取字典类型下所有字典值
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("sysDictType/dropDown")]
        public async Task<List<SysDictData>> GetDictTypeDropDown(string code)
        {
            var dictType = await _sysDictTypeRep.FirstOrDefaultAsync(u => u.Code == code, false);
            if (dictType == null) throw Oops.Oh("字典类型不存在");
            return await _sysDictDataService.GetDictDataListByDictTypeId(dictType.Id);
        }

        #endregion

    }
}
